{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "import random\n",
    "import time\n",
    "import collections\n",
    "from tqdm import tqdm\n",
    "sns.set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def build_dataset(words, n_words, atleast=1):\n",
    "    count = [['PAD', 0], ['GO', 1], ['EOS', 2], ['UNK', 3]]\n",
    "    counter = collections.Counter(words).most_common(n_words)\n",
    "    counter = [i for i in counter if i[1] >= atleast]\n",
    "    count.extend(counter)\n",
    "    dictionary = dict()\n",
    "    for word, _ in count:\n",
    "        dictionary[word] = len(dictionary)\n",
    "    data = list()\n",
    "    unk_count = 0\n",
    "    for word in words:\n",
    "        index = dictionary.get(word, 0)\n",
    "        if index == 0:\n",
    "            unk_count += 1\n",
    "        data.append(index)\n",
    "    count[0][1] = unk_count\n",
    "    reversed_dictionary = dict(zip(dictionary.values(), dictionary.keys()))\n",
    "    return data, count, dictionary, reversed_dictionary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('shakespeare.txt') as fopen:\n",
    "    shakespeare = fopen.read()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "vocabulary_size = len(list(set(shakespeare)))\n",
    "data, count, dictionary, rev_dictionary = build_dataset(shakespeare, vocabulary_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "GO = dictionary['GO']\n",
    "PAD = dictionary['PAD']\n",
    "EOS = dictionary['EOS']\n",
    "UNK = dictionary['UNK']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Generator:\n",
    "    def __init__(self, size_layer, num_layers, embedded_size,\n",
    "                 from_dict_size, to_dict_size, learning_rate, batch_size):\n",
    "        \n",
    "        def cells(reuse=False):\n",
    "            return tf.nn.rnn_cell.GRUCell(size_layer,reuse=reuse)\n",
    "        \n",
    "        self.X = tf.placeholder(tf.int32, [None, None])\n",
    "        self.Y = tf.placeholder(tf.int32, [None, None])\n",
    "        self.X_seq_len = tf.count_nonzero(self.X, 1, dtype=tf.int32)\n",
    "        self.Y_seq_len = tf.count_nonzero(self.Y, 1, dtype=tf.int32)\n",
    "        batch_size = tf.shape(self.X)[0]\n",
    "        \n",
    "        encoder_embedding = tf.Variable(tf.random_uniform([from_dict_size, embedded_size], -1, 1))\n",
    "        decoder_embedding = tf.Variable(tf.random_uniform([to_dict_size, embedded_size], -1, 1))\n",
    "        self.cells = tf.nn.rnn_cell.MultiRNNCell([cells() for _ in range(num_layers)])\n",
    "        self.encoder_state = self.cells.zero_state(\n",
    "            dtype = tf.float32, batch_size = tf.shape(self.X)[0]\n",
    "        )\n",
    "        \n",
    "        _, encoder_state = tf.nn.dynamic_rnn(\n",
    "            cell = self.cells, \n",
    "            inputs = tf.nn.embedding_lookup(encoder_embedding, self.X),\n",
    "            sequence_length = self.X_seq_len,\n",
    "            initial_state = self.encoder_state,\n",
    "            dtype = tf.float32)\n",
    "        main = tf.strided_slice(self.Y, [0, 0], [batch_size, -1], [1, 1])\n",
    "        decoder_input = tf.concat([tf.fill([batch_size, 1], GO), main], 1)\n",
    "        dense = tf.layers.Dense(to_dict_size)\n",
    "        decoder_cells = tf.nn.rnn_cell.MultiRNNCell([cells() for _ in range(num_layers)])\n",
    "        \n",
    "        training_helper = tf.contrib.seq2seq.TrainingHelper(\n",
    "                inputs = tf.nn.embedding_lookup(decoder_embedding, decoder_input),\n",
    "                sequence_length = self.Y_seq_len,\n",
    "                time_major = False)\n",
    "        training_decoder = tf.contrib.seq2seq.BasicDecoder(\n",
    "                cell = decoder_cells,\n",
    "                helper = training_helper,\n",
    "                initial_state = encoder_state,\n",
    "                output_layer = dense)\n",
    "        training_decoder_output, self.training_state, _ = tf.contrib.seq2seq.dynamic_decode(\n",
    "                decoder = training_decoder,\n",
    "                impute_finished = True,\n",
    "                maximum_iterations = tf.reduce_max(self.Y_seq_len))\n",
    "        self.training_logits = training_decoder_output.rnn_output\n",
    "        \n",
    "        predicting_helper = tf.contrib.seq2seq.GreedyEmbeddingHelper(\n",
    "                embedding = decoder_embedding,\n",
    "                start_tokens = tf.tile(tf.constant([GO], dtype=tf.int32), [batch_size]),\n",
    "                end_token = EOS)\n",
    "        predicting_decoder = tf.contrib.seq2seq.BasicDecoder(\n",
    "                cell = decoder_cells,\n",
    "                helper = predicting_helper,\n",
    "                initial_state = encoder_state,\n",
    "                output_layer = dense)\n",
    "        predicting_decoder_output, self.predict_state, _ = tf.contrib.seq2seq.dynamic_decode(\n",
    "                decoder = predicting_decoder,\n",
    "                impute_finished = True,\n",
    "                maximum_iterations = tf.reduce_max(self.X_seq_len))\n",
    "        self.predicting_ids = predicting_decoder_output.sample_id\n",
    "        print(self.training_state, self.predict_state)\n",
    "        \n",
    "        masks = tf.sequence_mask(self.Y_seq_len, tf.reduce_max(self.Y_seq_len), dtype=tf.float32)\n",
    "        self.cost = tf.contrib.seq2seq.sequence_loss(logits = self.training_logits,\n",
    "                                                     targets = self.Y,\n",
    "                                                     weights = masks)\n",
    "        self.optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate).minimize(self.cost)\n",
    "        \n",
    "        y_t = tf.argmax(self.training_logits,axis=2)\n",
    "        y_t = tf.cast(y_t, tf.int32)\n",
    "        self.prediction = tf.boolean_mask(y_t, masks)\n",
    "        mask_label = tf.boolean_mask(self.Y, masks)\n",
    "        correct_pred = tf.equal(self.prediction, mask_label)\n",
    "        correct_index = tf.cast(correct_pred, tf.float32)\n",
    "        self.accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_rate = 0.001\n",
    "batch_size = 32\n",
    "sequence_length = 64\n",
    "epoch = 3000\n",
    "num_layers = 2\n",
    "size_layer = 256\n",
    "possible_batch_id = range(len(data) - sequence_length - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(<tf.Tensor 'decoder/while/Exit_4:0' shape=(?, 256) dtype=float32>, <tf.Tensor 'decoder/while/Exit_5:0' shape=(?, 256) dtype=float32>) (<tf.Tensor 'decoder_1/while/Exit_4:0' shape=(?, 256) dtype=float32>, <tf.Tensor 'decoder_1/while/Exit_5:0' shape=(?, 256) dtype=float32>)\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "sess = tf.InteractiveSession()\n",
    "model = Generator(size_layer, num_layers, size_layer, len(dictionary), \n",
    "                len(dictionary), learning_rate,batch_size)\n",
    "sess.run(tf.global_variables_initializer())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_random_batch():\n",
    "    LOST, ACCURACY = [], []\n",
    "    pbar = tqdm(range(epoch), desc = 'epoch')\n",
    "    batch_x = np.zeros((batch_size, sequence_length))\n",
    "    for n in range(batch_size):\n",
    "        index = np.random.randint(0, len(data) - sequence_length - 1)\n",
    "        batch_x[n] = data[index:index + sequence_length]\n",
    "    initial_state = sess.run(model.predict_state, feed_dict = {model.X: batch_x})\n",
    "    for i in pbar:\n",
    "        batch_x = np.zeros((batch_size, sequence_length))\n",
    "        batch_y = np.zeros((batch_size, sequence_length + 1))\n",
    "        for n in range(batch_size):\n",
    "            index = np.random.randint(0, len(data) - sequence_length - 1)\n",
    "            batch_x[n] = data[index:index + sequence_length]\n",
    "            batch_y[n] = data[index + 1:index + sequence_length + 1] + [EOS]\n",
    "        accuracy, _, loss, initial_state = sess.run([model.accuracy, model.optimizer, \n",
    "                                                     model.cost, model.predict_state], \n",
    "                                       feed_dict = {model.X: batch_x, \n",
    "                                                    model.Y: batch_y,\n",
    "                                                    model.encoder_state: initial_state})\n",
    "        ACCURACY.append(accuracy); LOST.append(loss)\n",
    "        pbar.set_postfix(cost = loss, accuracy = accuracy)\n",
    "    return LOST, ACCURACY"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch: 100%|██████████| 3000/3000 [07:16<00:00,  7.02it/s, accuracy=0.744, cost=0.806]\n"
     ]
    }
   ],
   "source": [
    "LOST, ACCURACY = train_random_batch()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA4UAAAFICAYAAADnOVvjAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3Xd4W9X9x/G3JK/Ejp3EcfZeJ3uHACFAAoS9WqDQskpZpUChZbW/FuiitEBLKVAokDILFFo2lFEIEFZISAgJyckkezhO4hkvSb8/JCuSLHlbkqXP63ny+N5zz736nizpq7McXq8XERERERERSU3OeAcgIiIiIiIi8aOkUEREREREJIUpKRQREREREUlhSgpFRERERERSmJJCERERERGRFKakUEREREREJIUpKRQREREREUlhSgpFRERERERSmJJCERERERGRFKakUEREREREJIUpKRQREUl+acBg/08REUleLfr/PpneHDKB6cB2wB3nWEREpH25gD7A50BVnGPpCAYBa4FZwJY4xyIiIu2nP/AhMBxY19SbkikpnI7vN0BERFLHLGBBvIPoAPr4f+p9UkQkNfQhRZPC7QB795bj8Xhb/JD8/ByKisraLKhEpXYmj1RoI6idyaQt2uh0OujWLRv8//dLo/Qe2Qyp0M5UaCOonckkFdoIrW9nS98fkykpdAN4PN5WveHVPSMVqJ3JIxXaCGpnMmnDNmq6QNPoPbKZUqGdqdBGUDuTSSq0Edqsnc16f9RCMyIiIiIiIilMSaGIiIiIiEgKS6bhoyIiIh2OMWYk8BiQDxQB51tr14TV6Qn8AxgApAPvAVdba2tjHK6IiCQh9RSKiIjE1wPAfdbakcB9wIMR6vwcWGmtnQBMAKYC34pdiCIiksyUFIqIiMSJvwdwCvC0v+hpYIoxpiCsqhfoYoxx4tuXNwPYGrNARUQkqSkpFBERiZ8BwFZrrRvA/3ObvzzYb4CR+JYY3wG8aa39KJaBiohI8tKcQhERkcR3JrAMOAroArxhjDnDWvt8cx6Sn5/T6kAKCrq0+hkdQSq0MxXaCGpnMkmFNkJ82qmkUEREJH42A/2MMS5rrdsY4wL6+suDXQVcZK31AMXGmJeA2UCzksKiorJW7X9VUNCFwsLSFt/fUaRCO1OhjaB2JpNUaCO0vp1Op6NFXwBq+GiQTTtL+b+/fURNrfZCFhGR9met3QUsBc7xF50DLLHWFoZV3QAcB2CMyQCOBpbHKk4REWmd3zy2iA+XbYt3GFEpKQyycWcpy9bupri8Ot6hiIhI6rgcuMoYsxpfj+DlAMaY140x0/x1rgFmGWO+wpdErgYeikewIiLSfBu2l/CP11fFO4yoNHw0iNPhAMDb8pE1IiIizWKtXQXMiFB+QtDxOuCYWMYlIiKpQz2FQfw5IV5lhSIiIiIiHd78JVu56cFPWnz/0rW7efmjDa2KIVpusWrjXp57b22rnt1W1FMYxKGeQhERERGRpPH4m7ZV99/z/DIATpk5pMXP8ERILhau3MkDL60A4MzZw1v87LainsIgdT2Fkf7gRERERESkY2rPkYB1qzrf8/wyrvzzB/Wu7yutDqm7ZE1hICGsi601K0O3BfUUBtGcQhERERGR5PPwqyu55OQxbf7cLbvKuHnewnrlbo+HsooayipruePpJYHyi//4Xr2697+4nMW2kHk3zWnz+JpKSWGQA8NHlRWKiIiIiLS3isoabnvyCy4/dSz9C+rvr1dRWRP4jN4an6zY0eSk0Ov18s7iLTz9zppG667bVlyvrKi4kuv/9nGTY1tcbxei2FNSGKTur5tyQhERERGR9rd8wx627S7n5Y++4YrTxtW7fuXdH+J0OHjpzlMafVZ1jZsVG/YweWRBk1//ticWs3ZrMUdM6kt6mpNzjhrBDX/7hKKSygbv2128nxv+FnkBm+YkhMEe/+8qrvnetMYrtgPNKQxS9y2E5hSKiIiIiMRQA5+/m/LZvLyyhqvv+ZC//ucrNmwvabBuTa2HO55ewvL1Razd6uvpe3/pNt5ZtAW3xxsxIdy9bz+vfLSBu55ZwrJ1RWzeVdZoTM01f+k2thW2/XObQj2FQZyBLSniG4eIiIiISCoITN9qQt3tReVs2lnGjDG96l37x+urqK7xAFBRVQvAolW7Quq4PR5276tk7dZiVm7cy8qNe+s9p6bWE/G1b3jgQK/gim/2MmFYfhMibr6aWg9ZGbHvt1NSGOTAX0plhSIiIiIi7emjr7azdXe576SRj99er5f/e+gzAMYP7U7nrHS8Xi9vfLaJg0b1ZPmGonr33P/i8pDztVuK+cM/l9SrF2xvaVWTYl+2rv7rtYWaWjcoKYwvh3oKRURERERi4pHXVgaOvcCekkr2lVWzp6SSgq6dGNS7S+D6pb9/J3B85d0fcucVh/LaJxt5b8lWnp+/rt6z9/t7C4M1lhAC/OLhz5rZirZVHaWnsr0pKQyiOYUiIiIiIu3L6/XWG6b5xepCvlgdugpn8BYNO4oqQq6t3rKP95Zsjfj8u55ZSuvXK42PsooayM2M+evGPCk0xtwC3AqMt9YuD7vWGfgHMBWoBa6z1r4aq9g0p1BEREREUtliW8jQvrl06xKamDz+pmVY31xmju/T6td4+/PNPPPu2kbrVVTW7+2r8/eXv27w3o76cX7nngqG966/NUd7i+mAVWPMFOBgYGOUKtcBJdba4cDJwMPGmJj9rmifQhERERFJVR6vl/te+Io/PPVFvWvzl2wNGe65fH0Rby3cFPE5r33yDYtW7WLt1mL2V9Uy7/WVgQRv+YaiJiWEANf89cPmN6KDK99fE5fXjVlPoTEmE7gPOAeYH6Xad4ALAKy1a4wxi4DjgediEaPmFIqIiIhIKtq0s5SqGjcAu4sb3qMP4E//+hKA0v01nHToYKpq3KzfWsKkET349/vrA/VOP3woC5Ztp2tOJt86fChPvbW6yTHVujv2h/LxQ/P58RkTeOIty/tLtzXpnsmm6XsstqVYDh/9NfCktfYbY0y0OgMJ7UXcBAxozovk57e8Y7Gb/x9Abl4nCgq6NFK740uFNkJqtDMV2ghqZzJJhTaKiCSatxZuYkthORedOJo9JZXsr6qlX4Hvs/Ot//g8UM8RNCFvw/YSHn/TRn3ma5/4ProvWrWLnXv3c3DYdhEvfOBLEB3Ah8u2sXPv/jZqTeK79qyJAAzrm9fkpHDMkHwKC0vbM6yIYpIUGmMOAaYBN7X3axUVleHxtOxbhZJi31/SvXsr4vKHEUsFBV2Svo2QGu1MhTaC2plM2qKNTqejVV8Ciogkm+Xri3A4HYwd3B23x8OS1buZagoC06P2V9UGhm2ed+xIrrv/YyB0MZc6bo+Xi25/l2mjelJSXs3GHaH/Z9tNofv71SWGAJ9+vTNifK98/E2L29bR3Hft4TiDMuuDx/Zi3usHht4ePbU/Jx4yCLfHG/hzmD2lH5OH94h5rHViNafwCGA0sMEY8w3QH3jTGDM3rN4mYFDQ+UBgcywCBM0pFBEREZG2s2F7CRfd/i4791Y0XrmV/vSvL7nrmaWAL0m7/8XlLFmzO3D9908uDhxfduf7TXrmolW76q3Kv72ovElbO3RE1589qUn10ly+nCEz3RXxeqfMNDIzXEH1Q1OuzAwXeTmZdM/N4pEbZ3PbpQdz3lzDuKH5LYy89WKSFFprb7fW9rXWDrbWDga2AMdaa98Kq/occBmAMWYEMB34byxiBM0pFBEREZHmq6pxs+KbPfXKP/pqOwDL19e/1p6K/FOiyvyLlqzdUsyWwvKIdR9/03LR7e9Gfda+sM3c73p2aRtFmXgG9o48teGISX1Dzg/zr8Cal5MBQEa6k9GDutGtSybHTIs88+2+aw/n5gunMaJ/HnOm9A+UOxwOenfv3Bbht0pMVx+NxBiz1BhT9zt9B9DVGLMWeBW41Fobs3FU6ikUERERkeZ6/L+Wu55Zyo49oT2CbfmRcvXmfcx7bWXgc+rKjXvZva/+/LyaWk/IdgwVlbXcFtRLGG5+lL3+6oQvOlNSXt30oBPAT74zscl1s7PSA8e3fn86owd1A6B/QQ498rIAOHJyP045bAhZGS7mTvclgIN753L9OZO560czOefoERGf3SkzjcG9c/nZuVPrbfeRCOKyeb2/t7DueFLQcTlwZjxiggM9hS2ckigiIiIiKWjHHl8vXPi+enUfKZ99dw1l+2s49bAhLXp+cXk1t/u3iThp5mB6du3EHU/7hnDOu2kOS+yuQN3L7pwf6MkC2FPa+EqizRGPFUEvPH4Uj76xqkX3Oh0OenbrREFeFiu+2Vvv+vEHD+SNT+tvrTGwVxcuOM5w/wvLmT66J+8s8s1omzt9AF1zMrn/J0fg8Xop3Lc/au9gRxKXpDBROdVTKCIiIiLNVDfazOP1smjVLiaP7MGz765l/bZiwJdIvbRgQ8SksNbt4b+fbeLLdbu54ZwppKeFDuR74KXlLFx5IOm76YFPmBS0IMmydUXc/dyXIfcs8A9bBbj5kYWtb2Ccdcqsn7KkpzmpqfU0eq8DuP2yQwLn4UNlu2ZH77Xr2a0zt150EABHTOrHv95bS27nA72JToeD78yJ3DPY0SgpDKI5hSIiIiLSXHUdCwtX7uSdRVs47bAhvLNoS5PuvfSO+YHjy+6cz4/PmEB1rYc1W/YxsGeXkISwztK1BxaQCU8Igz0/f10TWxA/uZ3TKaloeMP2SB02nTJcUZPC7x0zkvlLt7I1yjzKYE6no9E6AMceNIC5Bw0IWVU0mcR9TmEicaCeQhERERFpnrq8oi4R3FdWFbWu1+tl554KvF5vvZU9Af7y/DL+9uJy3lm0JWQbg5aoW2gmkZ08s/EhtZE+mh85uR8Ah03oU+/aUVP706VTer1ygF//4CBGDewaOHc64PCJfenbIxvwrSjapXP9ex0OR9ImhKCewhAH5hQqKRQRERGRplm9pTjk3NFA8nDvf74K2SoiWdz0vSksWrWLdxb7EuOrz5jAPc8va/S+2VP68dTbq0PKfnvxDHbureCv//4qpHxk/7zA7/Wphw3hxEMG4XI5WbBsO+HGDunOqk376O5fIKZO/4KckAVlJg7vweyg1UD/es2sRmNORkoKgxyYUxjnQEREJGUYY0YCjwH5QBFwvrV2TVidx4EJQUUTgNOstS/HLFCRFFPr9lC+v4a8nIZXigzfyB2I2qPk9niSMiEEGDmgKyMHdA0khZOG92BY31zWbSuJek9eTka936srvzWevj2yAz13AF7/kj1dg1btdDgcpKdF3icQ4PiDB3HI2N50z82qd+2ISX1ZvLqQO684tN718D0FU0VqtjoKh/PAJGEREZEYeQC4z1o7ErgPeDC8grX2fGvtJP+K3RcAe4E3YxumSPLxeL1R56U99t9VXHvvR9TUukPK/7d4C7uL91Pr9t0XaSP3utVIw13yx/mtC7gD+Pl5U7nkpDHAgRX9g/O+meN789uLZ4Tcc8FxJnA8ZWRB4Pioqf358RkTGDXQtzXE0VMHMM0UMM0U0BinwxExIQQYNzSfeTfNiXo9FamnMIhTC82IiEgMGWN6AlOAY/xFTwP3GmMKrLWFUW77AfCUtTb6pCURaZIn31rN/CVbmXfTnHrXFq3y/ROsdXtJ939iLimv5qm3V/PU277z84419e4DIm59kGwuPXkMQ/rk8rO/fxpSPrxfHsP75QEH1um46tsHhpJedMJoSv1zHXv4k7IjJvVjysiCeou+fO+YkYHjV+46lcLCUob3Hx81ppsvnBYyNFSaTklhEG1eLyIiMTYA2GqtdQNYa93GmG3+8npJoTEmA/gucHRLXiw/P6cVofoUFHRp9TM6glRoZzK3cdU3e1i6ppCzjzENtrNu4/bu+Tm4whKSuk+Dbqcz8AxnRuhm8U+8adsu6DYw7xdzuei3b7X6ObdcfDC/evhTTjpsCKMGdefdRZv5wr8XohnUjdOPHM7MCX0BmDC8B50y0yL+Pp9z7Ch+/9jnHDKpP/sqanB7vPTsmUtP4IbzpjFheI/A8NzG+/6i/52dO2MQ44f3YPr4fi1qb6KJx79NJYVBtCWFiIgkuNOATdbapS25uaioDI+n5W9yBQVdKCwsbfH9HUUqtDPZ23j9Xz8E4OxjDIWFpVRU1tI568DH3ppaD39/ZUXgfOfOknr7A9b9W7n6rvn8/LypFBVXMrh3gifStbWtuj2nUzq/uuggunXJ5Eenj2fCsHzS05yMGZDHvrIqdu6pwPiHctb9/bnmjAkh58FG9OnCvJvmsL+skiP9q4TW1RvVL5fq/dUU7q9uUmwN/Z09e/awqDF0NK39t+l0Olr0BaDmFAYJ3nhUREQkBjYD/YwxLgD/z77+8kguAubFKDaRhLZ2SzFvLdyEx+tlT0ll1Hobd5Ry5d0fsHDlzgP3bi1mcdAI7fB5g1U17sCcQYCFX+/kwZdX8I83VrVhC9rWLH/SlePfiuHqMyZErDfvpjkRh8uCb3GYbv7FXKaagpBEuWtOZiAhlOSjnsIgdX/tlROKiEgsWGt3GWOWAucAT/p/Lok0n9AY0x+Y5a8jkhRq3R7e+GwTx04fQEZ69JUkw5VUVHPbk4sBqKx28+KCDfzxh4dQtr+GXXsPDPH0eLxs3OnrdXngpRW88ekmfnnBtJCED+DKu309i7dcOJ1Pv97BmwtDv5epW1Fz9eZ9zW9kjNTNv/vxmRP436ItgXl9dS45aQw9u3cKnB8+sQ8ffOnbymFQry5cdOJoenfvHLuAJaEoKQyiOYUiIhIHlwOPGWNuxreq6PkAxpjXgZuttYv89S4AXrHWJv8KFpIyFny1nRc+WM/qzfv46XcmNeme9dtK+O3jiwLnX6z2fYdyw98+qVc3fPTXxp2l3PXsUo6e1r9eXYBfPfp5U0NPCHf88FCu/9vHAIFFWob1zWPYKXlU1YT2fvbvmcOAngeGFdaNJD/tsCHMPWgAWRlKC1KZ/vSDBOYUxjcMERFJIdbaVcCMCOUnhJ3/LmZBicRI3XYQKzbsoai4kvy8+lsELFq1i/tfXM6MMb247JSxIQkhwL7y6HPSfvePhQwsyA4pW7lxLzPG9GqD6GPn9FlDeOHDDfXK8/OyOGpKf/73xZZ6+/1lhvW8dusSut/iyYcOZkdRBUdN66+EUJQUBtOcQhEREZHYCU5kKqpqyY9Q5/4XlwPw2dc7ueyUsfWulzSQFC5auZNFK+uXPxrDuYF52RkUNxBjuOmjevL5ql0hZSfPHMKg3rkM7ZtLVoaLS++YH7h2zjEjuOKsSRTvq4j6zAd+ekS94bkFXTvx8/OmNjkuSW5aaCaI9ikUERERaX+79lawa9/+kE3Ng6fvlJRXc/Mjn1G4L3QLiItufzdWIbaZs+YM58RDBoWUReupvP7sSfzwtHFMH9UTgL49sgNDXScMyyenUzpprtCP706Ho9H5mM2ZrympST2FQTSnUERERKT93fSgb8Pz4M3fPV4vNbVuLrvz/UDZ259HW4g3cZ1x5DCen78ucJ6bncE0U0D33Cxe/HA9pRU1HDmpL1+sLgwMn61T9wl0mr+38Eenj6NPfujw1+a46tvj+fobTUOWxikpDKJ9CkVERERaz+PxcvEf3+O8Yw2zJ/ejusbNwpW7mDm+d+BLeCCkp/DXjy6q95y6VT8T3VmzhzNjTC/2lVUxpE9uICnM7ZzO2MHdAZg9uR9frt3NsnVFeLy+1UDrhsaOGdyNr7/Zy5A+uYBvCOnUG2YHFo8Jd9Donk1aKXTyiAImj2jKtvCS6pQUBtGcQhEREZHWq1v58l/vriWnUzp/8yc/udnpZPv30QPwepLjM1ef/M5065IZWMzlkRtn8/HyHUwZGZqQff/4Uby1aDNmQFecTge9unVi5979nDvX1EvyoiWEAJefOq7tGyEpTUlhEM0pFBEREWm5/VW1ZGW4AklhVY07kBACbN5Vxr/fXx84/+c7a2IeY3so6Nop5NzhcDBzfJ969fJyMjnzyOGBc7c/KW4oARSJBSWFQTSnUERERFLVxh2lfLW+iJMOHVzv2pI1hfz1318BcPvlh9DTnwR5PF6efXctowd3457nlwG+TdQ/XbEj4msEJ4RwIClKBKfMHEzfHtm8tGAD5x9reOvzzSxZszti3d9ePINb//E5N35vMl2zMyNupdEUw/vnsbu4kk4ZWghG4ktJYRDNKRQREZFU9fsnF1Nd6+G4GQNDVrgs218TSAgBbnrAt0n84N5dGNo3l3e/2Mrbiw4sCPPpih2s21YSu8DbyDHTB5Cdlc5Bo30rg765MPoiN317ZPP3649s9Wt+//hRnDBjEF06Z7T6WSKtoaQwiOYUioiISEfzzY4SPB4Y2jc3ap2deyrIykwjLzt68lH3+aeiqpbOmWl8vHwHhfv2s7WwPMrrlvLNjtJ65R0tIRzYM4dNu8rqbf7ucrX/kM70NBf9e+a0++uINEZJYRCXfzx3Ig1lEBEREWlI3aqd826aE7XOz/7u2wLiym+NZ9KIHhHrZKa7qHXX8rcXljN2SHf+88H6iPUSWZrLQa07+ue47rmZ7CmpCim79qyJrN5STKfM0I/F58019OzaiW8fMYzCffvZVlROl04ZVNW62yV2kXhSUhikbpKvR0mhiIiIdEC1bg9X/+VDzjvWcMjY3vWu3/sf3zDQ844fzeyJoQuhlFfWAmA378Nu3tf+wbaDmeP78P7SbVGvX37qOG57YjEAp80awrgh+eTlZAY2iw+Wm53BmbN9i8L06t6ZXk3YAkKko3I2XiV1OB0OnA5wezyNVxYRERGJo+KyqnqfWcora6msdvPs/xpe1fOJN1aGnO8trYpSM7GdPWc4v7/s4MD5d48e0WD94f3yAsenzBzS4JBbkVSipDCMy+XE3cCwAxEREZF4q6pxc+29H/HEm6tb9Zxl64rYtLOUn973URtFFltzDxpIr24HevDS01yMHtQtcH6x9vMTaZKYDR81xrwIDAE8QBlwlbV2aVidW4ErgLp+/4+stT+KVYzgG4uuOYUiIiKSaL7ZUUK/Htmkpx3YB/CL1YWB65f88T2OP3hg4LykoprcBla1XLhyJw+8tKL9Am6hzplpVFTVRr0+d/oAJg7LJysz8sfY68+ZzEW3v8vBY3pxyqyhdEpz8PKCb6jWXECRqGI5p/ACa20xgDHmVGAeMCVCvcettdfFMK4QLqd6CkVERCSx7Cur4tePLuKQsb245OSxEeu4PV5e/XgjACUVNVxzzwJuvnAaxWXVEesnYkII0CMvi027yuiRl8Xu4sp610+ZOYTOWQ1/hL3nx7PIynDhcDiYPKKAySMK2itckaQQs+GjdQmhXx6+HsOE43I5cGtLChEREUkg1f6ewTVbfB+n6jZL8DbymeUP/1zCX/ybyieaaKul1m2NUdC1E5E2hahbLb4hOZ3SQ/ZaFJGGxXT1UWPMw8BcfP+XHRel2tnGmLnADuAWa+0nzXmN/PzW7fXicjpJT3dRUNClVc/pCFKhjZAa7UyFNoLamUxSoY0iTVFcVsXKjXs5OMJKocFcTl+CE76Xct2KodFUVSfekMn83CwuPmk0AOOH5vPV+iIABvbKYdPOMupm8QTnflNGFgSGyjoj5HpjB3djxTd7m/T6mRmuhPx9EYmnmCaF1tqLAYwx5wF3ACeEVXkA+J21tsYYcwzwkjFmtLW2qKmvUVRU1qotJdJcDsorqiksrL8ZazIpKOiS9G2E1GhnKrQR1M5k0hZtdDodrf4SUCQR/PlfX7JpVxnjh+WTnZUetV7dtll7Sqrwer3ck0C9fy5n5PUYJo/owZI1u+uV/+big8jK8H0Everb46l1e3B7vGzYXsKfnv2SAT1z2La7HIfT4etG8MJlp4zl8jvn4wUcjvo9hT8+cyK17qYNQrvn6sPQoDCRUHHpV7fWPgHMNsbkh5XvsNbW+I/fBjYDMV02yuVyaqEZERERaXNer5cFy7ZTU3sgeSn0z5lze7yUV9bUu+fj5dtZuTG0B+wvzy9j3baS9g02zPEzBtK/IDvitW5dMgPHl5w0huvOnsRDNxwZSPzCuYK6+tJcTrIy0sjOSmfckHxuu/RgTpk5GIBxQw58THQ44NJTxtK/IDvi8NG65zRFepqLjHRXk+qKpIqYJIXGmBxjzICg85OBPf5fwfX6BR1PAgYDNhYx1klzOXA38ZsmERERkabwer0sWbObea+v5MUF6wPldcNBr7lnAVfd/WG9OYIPv7qSO55ewtffHPjItGxdkwdQtZkeXTtx5OR+Ea8Fh3zIuN6MGdwdl9NJRnrkj5kuV/Q5gb27d6ZPfjZ/vuowjpnWP1DucMCMMb349Q9mROwpFJHWidXw0WzgOWNMNuDGlwyebK31GmNeB2621i4CbjPGTPXXqQbOs9buiFGMgH/1UfUUioiISBv54MttPPrGKk6bNQSANz7dxGmHDSU9zYk37DPH6s372FZUwdPvrOaWC6cHyh95LXSz+db48RkT+GjFThat3Nms+2ZP7seTb0XaF9HLn686rF7pmUcOp3tuFi98sD6k3NmEpC4v27eVxs/OncqnK3Y06R4RabmYJIXW2p3AwVGunRB0fEEs4mlIRrozZFiHiIiISGt89NV2AHbsqQiU/f2VFVx68ph6C8f84Z9LAse/fGRhm8dyy4XTGdS7C3srali0cifD+uWybmv9oah98jszon8eH3zpi93ldIT00N17zeFcefcHAHi8B5K4YJ2z0jj50MGBpPDyU8fy/tJt9eo1ZHi/PIb3y2vWPSLSfDFdaKYj6JSZRnlF/TH9IiIiIi0RyPuC8r/FtpDrt3xCbYz3Rh7UO3TlXzOgW72k8KRDB3ParCE4HQ5q3V4+Xl6/p65zVhoP3zCbB15ewbEHDaAxedkZHDS6FweN7tX6RohIm1NSGCYrI409ETZKFRERaQ/GmJHAY0A+UAScb61dE6HeWcAvCazHyNH+kTiS4OrmCYb3CpaUR95UPhbqYgkflTmsby7fOnxo4Dynk29F1OwIm8U7nQ6uOK3x9QB/ft5UCvKyWhGtiLQ37eoZxuVytGpLCxERkWZ6ALjPWjsSuA94MLyCMWYacCtwjLVR3SbJAAAgAElEQVR2HHAYUBzLICWyh15ZwSsfbQDgk+U7+N/iLfzi4c8orfAlfFXV7sBKoYm0DcLcGYMY2jeXOVP6h5SHr8r5rcOHcuHxo5g0ogcA1509id9cPKNZrzW8Xx55OZmNVxSRuFFPYRgtNCMiIrFijOkJTAGO8Rc9DdxrjCmw1hYGVb0WuLNu8TVrrRLCONlXVgVA15xMtu4u55MVvs7aMYO789CrXwfq/fieBdx7zSz2lFYFyj5ftSu2wfplpDmpDlsvoVuXLH5x/rSQsrNmD2fGmNDhnRnpLg6f2DdwPmZw9/YLVETiRklhmK27ytixpwKv16slj0VEpL0NALZaa90A1lq3MWabvzw4KRwDbDDGfADkAP8Bfmet1beYMfaTez8CYN5Nc7glaCGYxSE5vM99LyyncN/+mMUWjSPCvn7BfnT6eCqqapg1oW+D9UQkeSkpDLN+m+/L14qqWrKz0uMcjYiICAAuYAK+HsUM4L/AJuDx5jwkPz+n1YEUFHRpvFISaKydBQVdQuYI/nfhpnp1wjedbw+zp/bnvcVbGqzTKSONqmo3E4b3CGlX3fFxSf5nqr+zySMV2gjxaaeSwijURygiIjGwGehnjHH5ewldQF9/ebBNwPPW2iqgyhjzEnAQzUwKi4rKWjVvvqCgC4WFpS2+v6NoSjv/+cbXDV6PlXOPHkFJWVXEnso6U0cW8L8vtnDqzMGBdunPMrmkQjtToY3Q+nY6nY4WfQGohWai0LRCERFpb9baXcBS4Bx/0TnAkrD5hAD/BOYaYxzGmHTgKODL2EUq4Z5+p94CsXHhcDgY2b9rSFnnzAPf+f/gxNF895gR/PnKmQzpkxvr8ESkg1BPYRRabEZERGLkcuAxY8zNwF7gfABjzOvAzdbaRcAzwDTga8ADvAk8Ep9wU1f4lhKJ4qip/cnLyWBgry5UVNbSt0dnrvjTB2Smu5g5vg+AVv8UkQYpKQxz2enjefCFr7QthYiIxIS1dhVQb41/a+0JQcce4Cf+X9IGtheVU7hvPxOG9Yh4fd3WYp59by3Xnz2Z9DTfwKoXPlgfyxBDHD21P+/45w5OGVnAkZP6kpudAfiGiwVvCu/1ejll5mCmjCyIS6wi0vFo+GiYTP/+PEoKRUREktf/PfQZdz+3LHDu9Xr5YnVh4P3/0TdWsXZLMTv3VgTqfLJiR8zjBDhsQh/GDPFtBXHarCFc+a3xjBuaz8BekRejcDgcnDZraNTrIiLhlBSGcbl8S8y4E3SIiIiIiLS9RbaQe//zFW/6VxGtdfv29Utz+T4qPT9/HXtKqqLe31Z+8p2JEcsnDsvn6m9P4MRDBrV7DCKSejR8NEzd3oQ791TQs2unOEcjIiIi7WnD9hK+WldEdiffNlS7SyrxeLzs3OvbX9Dt9vDYf1fx/tJt7RZDdlYa5ZW1ALiC9kjunJlGz26dOOmQQTgcDiaNiDzUVUSktZQUhunVvTMAW3aVMX5ofpyjERERkfb0m8cWhZzv3lfJ8+8eWFn0qbdXs2rTvnZ7/XPnjmTOlP789vFFrN9WEvhyGuDuqw8L9FSKiLQnJYVhhvbLA0CDR0VERFLPV+uL+Gp9UeC8rRLCM48cRvfcLEYO6IrT6eDavy4AYM6U/gC4nL5k0OGAbx8xlFGDuikhFJGYUVIYJjPdhcMB+6tq4x2KiIiIJInjZgwM6QX83SUzKK2oCZyfeMgg7n5uGf175mAGdotHiCKSwvQVVBiHw0FWRhqV1e54hyIiIiKtUFFZy2df74x3GAAhCSFAn/xsRg44sOn8hGE9mHfTHLKz0mMdmoiIegojycpwUVmtnkIREZGO7JHXvmbJmt0M6JlD3x7Z7f56R07ux/nHGlZs2MNdzy4NlPfIy2r31xYRaQ31FEbg9Xr5ZHlifLMoIiIiLbO7uBKAmlrf9hJ7Siopqahu09eYZnwbxJ8yczDnH2sAGOvfU7DO/50/rU1fU0SkrSkpjGBfWTUer5e9pe2/H5GIiIi0D69/z+G6kZvX3f8x19yzALfH02av0Sc/2/8ajqh1GrgkIpIQlBQ2oG7jWhEREel4/DkhTqeDkvIDPYR7W7EJ/Q9OHA3AwF45nDt3ZGC18mh536mHDSG3c0aLX09EJBY0p7AB1bVKCkVERDqK9dtKWL6hiBc/3MC91xyOx3tgg6n7X1weOP7Fw5+1+DW6dslk3k1zAue79lYwf8lWDhnXO6TekD5dKK2o4dTDhrT4tUREYkVJYQRHT+3PO4u3UF2jFUhFREQ6it8+fmAj+g07SvD4c8KtheWs3nxgv8G2/NK3Z7fO3PPjWfXKf3nB9DZ7DRGR9qbhoxFMHtEDQEmhiIhIB3XXM0vZuacCgAdfXhHnaEREEpuSwggy0l2Aho+KiIikshu/O5lz544MKcvL1vxAEUk+SgojqEsKq7SBvYiISEo6ZeZgzMBuzJnSP6S8f0FOnCISEWk/MZtTaIx5ERgCeIAy4Cpr7dKwOi7gHuA4wAvcbq19OFYx1slM9+XKVRo+KiIikvD2llbx4ofr2+RZ580dyRNvrWZo39w2eZ6ISEcQy57CC6y1E621k4E7gXkR6nwPGA6MAA4BbjXGDI5diD6ZGb5ced3W4li/tIiIiDTT7U8t5sNl25t93/ih+SHnp8wczOwp/XnslmOZMKxHoDx8M3oRkWQTs6TQWhucYeXh6zEM9x3gIWutx1pbCLwInBmL+ILldk4HID3NFeuXFhERkSaqqnbj8Xop3FfZovuvPWtixPLuuVkh51eePp5po3ryi/Onteh1REQSXUy3pDDGPAzMxbfH63ERqgwENgadbwIGNOc18vNbP9a/Z89c8nIySEt3UVDQpdXPS1TJ3LZgqdDOVGgjqJ3JJBXaKO2rqtrND//0PsfPGIjT4QjZk7ClJo8oiFiemeHiitPGtfr5IiKJKqZJobX2YgBjzHnAHcAJbf0aRUVleDwtf2MoKOhCYWEpLqeD0rIqCgtL2zC6xFHXzmSXCu1MhTaC2plM2qKNTqejTb4ElI6roqoWgDc+29QmzwvekF5EJNXEZfVRa+0TwGxjTH7YpU3AoKDzgcDmmAUWJN3lpMatLSlEREQS0eerdjW5bkHXLE4+dHDEaw5HGwUkItKBxaSn0BiTA3Sz1m72n58M7PH/CvYccIkx5j9APnAaMCsWMYZLS3NSo30KRUREEs6mnaU88781Ta7v9cKps4bwysffBMpuuXA6AH/60UzKK2vbOkQRkQ4lVsNHs4HnjDHZgBtfMniytdZrjHkduNlauwh4ApgB1P1P/2tr7YYYxRgi3aWkUEREJJGs31ZC4b79PPjyimbd5/F6cTocjBvSneUb9nDtWRMZ1Ns3rzUvJ5O8nMz2CFdEpMOISVJord0JHBzl2glBx27gh7GIqTGbd5XhbsXcRBERkaYyxowEHsM3SqYION9auyaszq3AFcA2f9FH1tofxTLOePvt44tadN8JBw9qvJKISAqL6UIzHYkSQhERiaEHgPustU8aY84FHgQirXzyuLX2utiG1rEFLyCjd3YRkcjistBMR3Dw2F5kpOm3R0RE2pcxpicwBXjaX/Q0MMUYE3l/hBS0Zss+3vtiS7zDEBFJWuopjKJzZhrpSgpFRKT9DQC2+qdQYK11G2O2+csLw+qebYyZC+wAbrHWftKcF2qLbTziscfkRbe/2+J7g+PNSHcB0DWvc6PtSIW9NFOhjaB2JpNUaCPEp51KCqPweNFqZCIikkgeAH5nra0xxhwDvGSMGW2tLWrqA9pqL9+OJDje6ho3AMXFFQ22oyO2s7lSoY2gdiaTVGgjtL6dLd3HV11hUcxfshWAbbvL4xyJiIgkuc1AP2OMC8D/sy9h+/Raa3dYa2v8x2/7r4+LcawdQp/8zgBccVrob0+3Lr5VRrMy9J24iEgw/a/YiCr/t4oiIiLtwVq7yxizFDgHeNL/c4m1NmToqDGmn7V2q/94EjAYsDEON+YefWNls+oHLywT7ntHj2T0oG4M75/X2rBERJKKksJGuJyOeIcgIiLJ73LgMWPMzcBe4HyAsL18bzPGTMW33281cJ61dke8Am5v815fyYJl25t1T06n9AavZ2a4OGRs79aEJSKSlJQURnH8jIG88dmmeIchIiIJzhjzAr49Bl+rG97ZXNbaVcCMCOXBe/le0OIgO5iKyppmJYT9emSTnubkxu9OaceoRESSl+YURjFiQFdA+xWKiEijPgRuBnYYY/5mjDk03gF1fE0bpVPXM3j9dydz84XTycxwtWdQIiJJS0lhFHXbUZRWtOhLXxERSRHW2j9Za6cAhwP7gKeNMWuMMTcbY4bFObwOZ+OOUioqm/be6/X6vrh1OjTVQ0SkNZQURtEjLwuA4rKqOEciIiIdgbV2hbX2Z8C5QAVwC/CFMeYdY8zE+EbXMazbWsyvHv2c3z2xuEn1xw7pDqB9hUVEWklzCqPIzvINSams1uqjIiLSMGOMwZcMfhffIjBPACfh23z+CuBFYEjcAkxAJeXVVNa46dm1U6DsxQ/XA1BcXt3o/decOZHRg7rxrSOGkZmuYaMiIq2hpDCKLP+8hP3V2sBeRESiM8Yswrc9xLPAd621n4VV+ZMx5qqYB5bgrr13AV4v/O0nR/DbJxZx4XGjqHE3bR5/8LYTwUmliIi0jJLCKNJcvqEom3eVxTkSERFJcLcDL1tro3ZvWWvVSxjGPx2QjTtL2VpYzjPvrmHjjobfc0+fNYTDJvSNQXQiIqlFg/AbsTh072AREZFwJfh6CgOMzzHxCadjqVsjZt3WEmrdngbrnTxzCN26ZMYoMhGR1KGkUEREpHXuA0rDykr95dIIRxO3n5gyoqCdIxERSV1KCkVERFqnp7U2fKf17UDveATTEcx7bWXg+OFXv27SPaMGdWuvcEREUp6SwgYcMrYXLqf2PhIRkQatN8bMCSs7EtgQh1g6hAVfHcihd+3b32j9u340kzlT+rVnSCIiKU0LzTSga04mDm2IKyIiDbsV+I8x5hFgHTAM+L7/l7TSpOE9NI9QRKSdqaewAWu3FlPr9mgDexERicpa+xIwF8gGTvT/PNZfLq101bfHxzsEEZGkp57CBuTnZrGGYjYXlpGXo28pRUQkMmvtQmBhvONIJkdO6suoQd00YkdEJAaUFDbghEMG8enXO6mo1Ab2IiISnTFmEjAL6AEHltO01t4ct6A6sPzcTM471ighFBGJEQ0fbUBedgYAxeVR9yMWEZEUZ4y5FPgImAPcCIwHfgoMj2dcHdlU01MJoYhIDCkpbEB2p3QAdu+rjHMkIiKSwG4AjrPWng7s9/88A6iJb1iJyeP1xjsEEREJ0+Sk0Bgz2xgzxH/cxxjzmDHmH8aYpN2Hyen/lvLtRZvjHImIiCSwntbaD/3HHmOM01r7BnByPINKVM/+b22jdZzqJRQRianm9BTeD7j9x3cB6YAH+HtbByUiItKBbDHGDPYfrwZONcbMAlJ67oHX6+XNhZsC8/KLy6u56PZ3m/RFq3JCEZHYas5CM/2stZuMMWnAscAgfG942xq70RiTDzyBb++mamANcJm1tjCs3qPA0cBuf9Fz1trfNSPGdrO/qpZOmVqXR0RE6vkjMBr4Bvg18DyQAVwdx5ji7uuNe3n23bVs2lnKJSePZeOOkibfO7RvXjtGJiIi4ZqT5ZQYY3oB44CvrbVlxpgMfD2GjfECf7TWzgcwxtwB3A78IELd26219zYjrpgo21+jpFBEREIYYxzAB8AmAGvtG8aYbkCGtbYsrsHFWW2tB4Cy/bVs2F7CjqKKJt33i/OnMbRvbnuGJiIiYZozfPSvwOfAU8B9/rKZwKrGbrTW7qlLCP0+xdfTmPC+fcRQwNdTKCIiEsxa6wW+wjedoq6sOtUTQiCweqjX6+U3jy3imXcjzyX84w8PCRynuZxKCEVE4qDJXV/W2j8YY14A3Nbadf7ircDFzXlBY4wT+CHwcpQqPzHGXAasA35mrV3ZnOfn5+c0p3pEBQVdAseTRvXi3++vp7iyNqQ8GSRbe6JJhXamQhtB7UwmSdbGJcBImvAlaSpx+ucFLt+wJ2qdUQO70iOvU+B8mBJCEZG4aNZ4SGvt6rpjY8xswGOtfb+Zr/lXoAyINET0/4Dt1lqPMeZ84L/GmKHWWneEuhEVFZXh8bR8ueuCgi4UFpYGzqsrfSuK//npJYwf1K3Fz0004e1MVqnQzlRoI6idyaQt2uh0OtrkS8A2Mh/f+9WjwGZ8UyYAsNbOi1NMcdeUfQanj+oZcu50aoUZEZF4aM6WFO8bY2b6j28EngH+aYz5eTOecScwAviOtdYTft1au7Wu3Fr7OJAD9G/q89tDZ80jFBGRhs0ENgBHAOcC5/l/ndvUBxhjRhpjPjHGrPb/HNFAXWOMqfC/pyasyuqGp104HQ6OnNwPgB+dPg6AQ8cl7S5XIiIJrTkZzzh8cwEBLgFmA6XAR8Btjd1sjLkNmAqcaK2tilKnn7V2q//4WHxbYGxtRoxtLj8vK54vLyIiCc5aO7sNHvMAcJ+19kljzLnAg8Cc8ErGGJf/2ott8Jrtpmx/Dfe9sLzBOhnpzkBv4lTTkzuvOJTuuXrPFRGJh+YkhU7Aa4wZBjistV8D+FdZa5AxZizwM3z7N31sjAHYYK093RizFDjBWrsNeMy/wqkHKAFOsdbGdYWXNFdz1uIREZFU458rH1GkUTER7u8JTAGO8Rc9DdxrjCkI37oJuAl4Fd9ImoQZPxtub2nE735DhI8uVUIoIhI/zUkKF+CbB9gHeAHAnyDubugmAGvtCiDiRAFr7aSg46ObEU/M7Smp1JuWiIiEqyVoHmEYVxPuHwBsrZs/b611G2O2+csDSaExZiK+fYJnA79sVcTtbHtReaN1HJE/FoiISBw0Jym8EPgpvjeoO/xlo4C/tHFMCad3987s2FPBdfd/zMM3zsbZhMnzIiKSMoaEnffB16P3Slu9gDEmHfg78H1/0tii57T1Ct3hPB4vi1bu5IGXVkSt0zu/MzuKKnC5HAm9Cm0ix9ZWUqGNoHYmk1RoI8Snnc3ZkqII+HlY2WttHlECGjWwKzv2+DbdfX/pNmb7J8aLiIhYazeGFW00xlyAb2/fR5rwiM1AP2OMy5/wuYC+/vI6fYBhwOv+hLAr4DDG5FprL21qrG29Qne4/y3ewlNvr456HeCWC6fzw7veZ/KIHgm70q5WAU4eamfySIU2Quvb2dLVuZucFPq/pfwFvhXV+gLbgCeA31lrq5v9yh2Ix3vgDXTTzuT/yygiIq2WCxQ0paK1dpd/fv05wJP+n0uC5xNaazcBPerOjTG3AjnW2uvaMujWKiqpbLROZrqLP185k+xO6TGISEREmqI5w0f/CBwEXA5sBAbhm9OQC1zb9qEljtNnDeWDL7cDkJ6mhWdEROQAY8wThM4p7Awcji/Ba6rL8S22djOwFzjf/+zXgZuttYvaKNx21Vgv5NSRvjw5LyczFuGIiEgTNScpPBOY6B9GCmCNMV8AX5LkSWHwm5f2LRQRkTBrw87LgQeste809QHW2lXAjAjlJ0Spf2tzAoyVtz7f3OD1H542LkaRiIhIczQnw4m2ukpKrLryyI2z+cEf3uPlj77h2IMG0knJoYiIANbaX8U7hkTw6YodUa9dePwovlpfVG8bChERSQzNyWyeA14xxvwK2IRv+Ogv/OVJzxH0Tra/qlZJoYiIAGCMuQd4xlr7cVDZocBZ1tpr4hdZbP39la+jXjt8Yl8On9g3htGIiEhzNGeC3A3AO8B9wGLgr8B7wPXtEFdCK9tfg9vT6H7EIiKSGs4Bwuf8LQa+G4dY4ibNVb8bcO70AWRmNGWrRhERiacGu7uMMXPCiub7fzk4MKn+MODdtg4skd36j8+ZNLwHV58xId6hiIhI/Hmp/yWrK0JZUvPt4Ru60MzZR43g7KNGxCcgERFpssbGQEbbX6nuf/26d4ChbRZRArvmzInc/dyXACxduzvO0YiISIL4EPitMeYGa63HGOMEbvWXpwyHJgyKiHRYDSaF1tohsQqkI8jQdhQiIlLfj4FXge3GmI3AQGA7cHJco4ox5YQiIh2XspxmSE8P/e16acGGOEUiIiKJwlq7BZgCnArcAZwGTPWXp4SthWVUVrvjHYaIiLSQksJmyEgLnSyvpFBERIwxk4B+1tpPrbXPWWs/BfoZYybGO7ZYqKpx88tHFtYrP2pq/zhEIyIiLaGksBk0fFRERCJ4EkgPK8sAnohDLDFX6468GreGk4qIdBzKcpoh0hvcyx9t4KLb36WmVltUiIikqIHW2vXBBdbadcDg+IQTW26PN2K5U1mhiEiHoaSwGbrmZNYre3PhZgCqazWXQkQkRW0xxkwJLvCfb4tTPDHldkdOCscN6R7jSEREpKWUFDZDRrqLR26cHVK2v6oWgMW2MB4hiYhI/P0ZeMkYc5Ux5gRjzFXAC8Cf4hxXTLgjDB8dOaAr44bmxyEaERFpCSWFzRRtH6ZH31gV40hERCQRWGsfAn4CnIhv9dETgJ9aa/8e18BiZFtReb2yrAxXhJoiIpKolBS2wM/OndJ4JRERSSUfAPcDdwHPAbnGmIviG1JslFbU1Cs77qCBcYhERERaSklhC4zo35W7rz6sXnlFZQ0eb+S5FSIikpyMMacBa4FfAQ8AVwEPAufFM65YeeS1lSHn826aw6hB3eIUjYiItISSwhbq0il89XG48u4PeeGD9RFqi4hIEvstcJG1djJQ7v95KbA4vmHF3vePHxXvEEREpAWUFLZQtLmFr32ykS/X7g4sQCMiIklvoLX2ubCyx4Dz4xFMPB02oU+8QxARkRZQUtgO/vL8Mh58eUW8wxARkdjYZYzp5T/+xhhzCDAMSPrVVj5ftSvkPNoXpiIiktiUFLaTZeuK4h2CiIjExkNA3UTzPwPvAV/iW3gmqa3YsCfeIYiISBtIi3cAyWxLYRn9C3IC558s34Hb49XwGhGRJGKt/UPQ8ePGmPlAtrV2ZfS7ksP2CNtRiIhIxxOTpNAYkw88gW84TTWwBrjM2tAd340xnYF/AFOBWuA6a+2rsYixJUYN7MqqTfuiXr/5kYXMu2lO4PyhV78GNOdCRCSZWWs3xTuGWFmzpTjeIYiISBuI1fBRL/BHa62x1o4H1gG3R6h3HVBirR0OnAw8bIzJiVAvIVx39mT+fv2R3H7Zwc26z6ttK0REREREJEHEJCm01u6x1s4PKvoUGBSh6nfw7e2EtXYNsAg4vt0DbCGn00Gay0nPbp2j1ln5zR6qqt2U7T+wua/2MhQRkWRy+qwhzJnSL95hiIhIC8V8TqExxgn8EHg5wuWBwMag803AgFjE1VqTR/RgyZrd9crveGYp00f1pKrGHSjzeMClJX5ERKSDG9KnC9t2V3DyzCHxDkVERFohHgvN/BUoA+5tj4fn57d+tGlBQZdm3/PLiw+mpLyaC3/9Vr1rO/ftx+U8sEx39/xssjLiv8ZPS9rZEaVCO1OhjaB2JpNUaGNTGWNG4tvXMB8oAs73j5YJrvN94FrAg2+ri4estffEOtZg67YWs2F7aTxDEBGRNhLTzMQYcycwAjjZWuuJUGUTvmGldQvQDMS3tHeTFRWV4fG0fHhmQUEXCgtb/ibXKdPF/ip3SNmmHaX07NopcP7ju+bz64sOwumM335OrW1nR5EK7UyFNoLamUzaoo1Op6NNvgRMEA8A91lrnzTGnItvGsWcsDr/Bh611nqNMV2A5caY+dbaZbEOts7qLdEXWhMRkY4lZoMYjTG34VtV9DRrbVWUas8Bl/nrjwCmA/+NTYRt43eXRF50Zte+/YHjbbvLKa2ojlVIIiKSoIwxPYEpwNP+oqeBKcaYguB61toSa23dN56dgXR8i7iJiIi0Wqy2pBgL/AxYDXxsjAHYYK093RizFDjBWrsNuAN41BizFnADl1prO9RX5l1zMhneL4+1Wxtepnt/tZu8GMUkIiIJawCw1VrrBrDWuo0x2/zl4ds2nQL8Ht/2Tj+z1n7V3BdryykWOdmZ9cqSSTK2KVwqtBHUzmSSCm2E+LQzJkmhtXYFEHGspLV2UtBxOXBmLGJqTzd+bzKvfbyRFxdsiFqnpLya3t2jr1oqIiISzFr7MvCyMWYg8KIx5nVrrW3OM9pyikVZ2YFBP8k25FnDuJOH2pk8UqGN0Pp2tnR6hdbAbAcupxOXq+H5grc/9UWMohERkQS2GehnjHEB+H/29ZdHZK3dBCwETopJhFE8N39dPF9eRETakJLCdpLWhD0nKiprGq0jIiLJy1q7C1gKnOMvOgdYYq0NHzo6Oui4BzAbaPbwURERkUiUFLaTOVP6kZXharDOlXd/GLKpvYiIpKTLgauMMauBq/znGGNeN8ZM89e51Bizwj8P/3/Avdba+nsgiYiItED8N8tLUulpLs48chhPvLU6UHbh8aN49I1VIfWu/suHzLspfOVxERFJFdbaVcCMCOUnBB1fG9OgREQkpainsB0N7pMbOJ530xwOHdc7Yr1fP/o5JRXVzF+6Fa9XK4yLiEhi8+i9SkQkqainsB0N6ZPLdWdPYmAv37KyaS4n3XMz2VMSuk3jNztKueaeBQD0zc9m5ICuMY9VRESkqdzuA0nhT86aGMdIRESkLainsJ2NGdydnE7pgfOffmdSA7WhoqoWgOXri6ip9bRrbCIiIi1RXesG4KzZwxk3ND/O0YiISGspKYyxPvnZHDWlf9Tr9zy/jHe/2MKf/vUll905n1q3EkMREUksH365HYCNO5N/zzARkVSgpDAOvnXEUMYN7R71+pNBi9PsKa2KWk9ERCQelq7dDcBevUeJiCQFJYVx0CkzjZ+c1fAw0jpu9RSKiEiCqXtvSnc54hyJiIi0BSWFCa7W7eXmRz5j0apd8Q5FREQEgFL/HrsThveIcyQiItIWlHghf3QAACAASURBVBTG0U/OmsgpMwdz1uzhUes89fZqthSW88jrK2MYmYiISHS79u4H4Oip0efIi4hIx6GkMI7GDc3ntFlDOfagAVHrrN68DwCnw8GiVbu0j6GIiCQMh0PDR0VEkoH2KUwATXlT3V9Vy/0vLgfge8eMJCPdyawJfds7NBERERERSXJKChPEjd+dzB/+uaRJdZ9627c66ZrNxewu3s/VZ0wgK0N/lCIi0v48Ho1YERFJNho+miDMwG48fONsLj91bJPvWfDVdlZt2hdYGrzOG59t5Ol31rR1iCIiIrg9WhVbRCTZKClMIE6Hgy6d0pt9X/g0w+feW8fbiza3UVQiIiIH1Lp9bzoNzYcXEZGORUlhghk9uDunzRrSrHseeuXrdopGREQkVK1/j8IeeZ3iHImIiLQVJYUJ6JSZoUnh2MHdGr3nibesegdFRKTd1fUUurRxvYhI0tDqJAnuByeO5tBxvfn5Q5+xc09F1HrvfbEVgMVBm9x/9vVOZozp1e4xiohI6nD7ewrTnPpeWUQkWeh/9AR10/emcOphQ5g5vg8Oh4Prz57UpPtWbykOHD/48go2bC9h2+7y9gpTRERSTK1/9dE09RSKiCQN9RQmqJEDujJyQNdWP+c3jy0C4OKTRjPN9CQ9zanNhkVEpMXq5hSmufS9sohIslBS2EFkZzV/VdJgD7+6kodfXQnAT8+exJEFXdoiLBERSTFuzSkUEUk6+pqvg8jMcPHwDbPb5Fl3PbM0YvnarcVU1bjb5DVERCQ57SurAtRTKCKSTPQ/egfidDo4ZGzvNnnWjqJydu/bz7/fX4fX66W4vJrbnljMD+96n62agygiIlHc98JyANwebyM1RUSko9Dw0Q6mU6arTZ5zyW3vBI5n/H979x0nVXX/f/w1s51dWGALsEtvh967FCE2LNFgQRM1iuarRsVE/Ro036jRGLEbjIoNWwwafiaWiDEqgiAiICCicEB6k7IsC2wv8/tjZmdntgFbZnZm3s/Hg4dzzz33zjlelrOfe+79nN5tiIutOO/y7/fxs/FdG+R7REQkvJS/U5hfWBLkloiISEMJWFBojHkUuBDoDPS31q6rps69wK+BPZ6iL6y1NwaqjaHgolO7kd4ygbEDMgAXG3flMOv/ra3XOed/tZ1l3+3zbr+/dJuCQhERqVVJSVmwmyAiIg0kkDOF7wB/ARYfp95r1trbA9CekBQfG80ZIzp6t2ta2P7KMw2vfWRP6Jy+AWFlLpcLh8PBoSMFREU5SU6MPbkGi4jIcRljegKvAilAFnCltXZTpTp/AC4FSoFi4C5r7UeBbuuAbims3ZzFiN5aB1dEJFwE7J1Ca+0Sa+3OQH1fpPB90f/KM433c30Xrd9zMJf5y7ZzzUOfUVhcyu3PLOW3Ty3xq5NfWMJrH1k+XrmTvILien2fiEiEmw08ba3tCTwNPFdNneXAcGvtAGAa8JYxJiGAbQSgWVw06S0T/F47EBGR0NYU3ym81BhzBvAjcI+19stgN6gpK19zsFfHlkwYlEH79CS6ZybX+7ybdh3mgy+3AXD4aGG1deYv287C1bsBWL8tm+kXDaj394qIRBpjTDowBDjdUzQX+KsxJs1ae6C8XqVZwbWAA/fM4q5AtRWguLSM6GjlqRMRCSdNLSicDTxgrS02xpwOvGuM6W2tzTrRE6SkJNW7EWkhtobf6/eeRbP4aGJjokhPb9Eg53z1PxWPns5btMX7eduBXIb3cWdAXb/9sLd8/Y7sJvv/ram2qyFFQh9B/QwnkdDHk9AB2G2tLQWw1pYaY/Z4yg/UcMyVwGZrbUADQnCvUxjt1BqFIiLhpEkFhdbaH30+f2yM2Qn0Axad6Dmyso5RVo802WlpzTlw4Gidjw+WnIKiKmVXTe7FKx9uqPe5V9n93s/3vfQVt106iL6dW7NlT463vLCotEn+fwvV63kyIqGPoH6Gk4boo9PpaJCbgKHIGDMBuJ+KmcUT1hD/zxxOBwnxMWEf2Id7/yAy+gjqZziJhD5CcPrZpIJCY0ymtXa35/Mg3JlKTyxbilQxvFd6jUFheutm7D+UV6fzPvbmmmrLy8pcOH3uHu/Yd5QfducwaUj7On2PiEiE2AlkGmOiPLOEUUCGp9yPMWY08DfgfGvtSY+PDXHjNC+/GBeE9c0L3ZwJH+pn+IiEPkL9+1nXm6aBXJJiFjAFaAt8YozJstb2NcbMB+621q4E/myMGYo7s1oRcIXv7KGcnIS4aF763URycotYuzmLVz7cwDCTxjXn9CEmIZZrH/i4Qb/vQE4+AItW7+Giid249+UVAIwbkEGM3j8REamWtXa/MWYNcBnugO8yYLXv+4QAxpjhwFvARdbaVYFvqVtxaRkJSjIjIhJWAhYUWmunA9OrKT/b5/MvA9WeSOFwOGiZFMf4gRmM6deWKKcDh8NBWutmPHz9aO6Y7c7jM2fGJEpKy9i8O4eH/r66Tt/17y+28cU6dwy/NyvXW37LrMXcf81IUpLj698hEZHwdD3wqjHmbiAb9zuDVLpx+gyQADxnjDfb9BXW2m8D2dCi4lItTyQiEmaa1OOj0rh8l68AaNUirsr+nh1a1vn85QEhwDebK3IDFRSV8r/PLqVFYixHcouYOqk7Ywe0A2Dh6t1MHtUJp0NJC0QkcllrNwAjqyn3vXE6PKCNqsGhI4VkpkXm+5wiIuFKQWEEi3K6g8RTB2d6yxwOh3dh4oZ2JNedDOetBT/w1oIfvOVtWzejTetmtK/0S8bazVl8tmoXt1w8sMHbIiIiJy8rJ5+8whK++n4f1/20b7CbIyIiDURBYYSbM2NSlbJAPxb09L/Wedvy6JurKStzccfPh/DU22spLXNRUFRCfKz+qoqIBFtWTkGwmyAiIo1Av2lLFSf7JGfvTq1Yvz273t/7q4c/o9QnK15CXDTH8ovJK6g+KCwpLaOgqJSkhJh6f7eIiByfU+sTioiEJaWElCoGdEuttvyCsV2qLR/WK71Bvtc3IDx4ON+7vW7roWrrv/jv75n+l8W4XHVPry4iIieupKQMgEsmdg9yS0REpCEpKJQqhvRM45lbx/PgdaOYM2MS3TOTAejVqVWVug5gTL+2Dd6GO2Z/SX5hCQCvfLiBvIISso8Wsuw7dzKb4pJSlq/fD0BuQQn7D+fzP498xt8/2djgbREREbf129w36fp0rjoeiIhI6FJQKNWKj42mTatmAGSmJQLQLD6anu3dAeJET3Ka/t1SiIuJYsYvhjRqe2568nNue/oLnn//e/75+Raue3SRd9+OfUeZMftLSkpdfLJyl99xC1bu4Gu7/7jnX/zNHuyO+j8CKyISzua8/x2AHtsXEQkzeqdQjuvnp/VgeK902qclcfNFA5j7ySYuOrUb/bumeJewqM9SFifr30u3+W0/+uYav+0d+47SsU1zAJ6Y615zsbqEOr5e/nDDCdUTERH3O98iIhI+NFMoxxUTHUWfzq0BSIyP4dpz+5AQF82gHqk0i/f/xWDikMzqThFQr/5nA2WV3jMsLinjiX98w7SZC1i18cBJnc/uyObTr3cdv6KISBjz/Xc1PjYqiC0REZGGpqBQGsycGZO44gzj3b5v2gh+ekrnKvXG9GvLg9eNarR2bN17lL99ZDl0pCJ1+sZdh/l2i3vtxZc++J7127PZl53HkbyiKscfyy9m6bq93u2H/r6aNz7Wu4oiEtkKPO95g3tNWxERCR96/kMaXIvEWAqLSmmfnkT79CQ+/XoXuQUVv0xcNbkX0VEV9yNSWsSTdaRh175auGYPC9fs8W4/5vOIaX5hKY94HiuNi4ni2dsm+B37wvvf8+2WLLpmJNO2dbMT+r78whIOHM73PrYqIhJuCopKg90EERFpJAoKpcE9+usxfttP3DyWd5ds5dstWZw1sqM3ILzxZ/3JSG3G4WNFPDJ3NanJ8Rz0WRj5jOEd+O+KnY3a1sLiUqbNXOBXVh6g3vX8Mu67ZkStxx/LLyYuxsmNT3wOQLO4aC79SQ/GDmjXOA0WEQmS8ve5Y6P1kJGISLhRUCgNzncWsHz7wgnduHBCN7/yoSYNgHYpid4EL+UB2l+mjwVo9KCwsuyjhew5mOvdvvul5d7PRcWlvPHxRqaM70pyUhyFRaVM/8tiv+PzCkuYM389g3qkHjc735K1e8nJLeSc0Z0btA8iIo2h/J3CWy4eGOSWiIhIQ1NQKE3KXVcMZX92Hs2bxQbl+297+osa99336kr2HMzlh9053HLRAO58blmNdWe/u47bLx1c63fNmb8eQEGhiISEwmL3wvUmgNmmRUQkMPQMiDQp3TOTGdOv4tHL3p3cCySfPqxDtfVn3TKO/zmvT0DaVj6DuDcrjxnPLcNVS929WXnsOZjL2s1Z7MvOo7ikFJfLxd6sXF7/r+XtRZu9dUvLyvjfZ75gxQb3eoo/7Moh3yehQzmXy8WHX23naDXJcUREGltMtJPE+GicTiWZEREJN5oplCbtt5cMpLTUxT8/3wLAeWM6M6RnGn98ZQXgXkB5VN+2vLtkK/uy84PZVD/ZRwv5vxe/8iu7cEJX3l60pUrdBV/vJutIIa98uJ712w6xcM0eBnRLYWjPNFonx9PXsxzIlj1HmPfZZjbuOMwtFw/k0693sXDNbmbPOC0gfRKRyOZyuWimRetFRMKSZgqlSYuOchLnsx5Ws/hoOrWtmuHzwetGc8bw6mcTxzWRpC/VBYQAcz/dBLizopZnTF27OYuXP9zglzW1pLTMU889i/jGxxvZfSAXl8vFzU9+zsI1uxuz+SIS4Vwu0ByhiEh4UlAoIWHCoAziY6MYZtIB+MMvh3H12b386kyd1J2Hrx/NXZcPpZPP0hBXn93b+/mRG/wzo4aC77YdAty/kAFQaX2wklIXuQUlvPYfyzUPLeDg4Xz2Hcrjtqe/IPtoYYBbKyLhyuXS+oQiIuFKj49KSMhITeSZWyvWE+zSrgVd2rXwq+NwOEhtmUBqywRu+Fk//vr2tzx441iKC4qYfdsEHA6H37t6910zwi+7aFP1z0Wb+X7rIT78agfgvlO/Y99R7/4vvqmYIXS54KPlO3E43I+wrtiwv8YZ1HK7D+bSPCGGFonBSe4jIqHBhavyPSkREQkTmimUsJTeMoH7rhlBy+ZxAMTGRBHjs7ZWUkIM7dOSvIlsAG6bOijg7TwRW/ce9QaEAJv35HDvyyu824/9fZVf/U9X7SLPE/zmF5awaddhDhyu+X3LP7z4FXc9XzWT6ntLtrJ2c1Z9my8i4UIzhSIiYUtBoUSUhLhoHLgfNQW47LQeAAwzafTt0poB3VK8dR+6fjR3XzXMu328dQcDpaS0trynbkvX/QjAu0u28uDfVvG72V/y+Ftr2Lr3CACHjhRw+FjFo6XlQeTGnYe97y6+s2QrT877pqGbLyIhqszl0juFIiJhSo+PSkSJiXby0oxJ3u32aUnM8dk+d0xn1m7O4uYp/UlrmUAaCVz6kx4MM2m0ah7Hv7/czr8+38KpgzNZuDq0Erus23qIdVsPcevUgTz+ljvYe/F3E737dx04xsw33LOOvsFxXkExzeLrFxD//oVlnDWyI+MGZNTrPCISXJopFBEJT5opFPHRPTOZv/5mPIN7pnnLzhjegdYt4nE4HJw3pjNzZkziyjMNY/q1rfE8Z43o6P3cPi2pUdt8ssoDQoBrH/rM+3nOB+u9n30fG73pycXVnsflclFYXMqRvCIKiqquq+hbb29WHi/P31CfZotIkJW5wKnfGkREwpJmCkUqaRZ/Yj8W157bh7NHdWLXgWO8u2Qre7PyvPsumdSdcQPb4XK5k+RMm7mgsZrbYLb9eLTGfd9tPUTfLq39yhau2cPrH1kAUpPjediT2TWvoJiv1u+nQ3oS3TOTK7KmAgcO55MYH13vmUcRCTyXy4UWpRARCU+65ydSDxmpiYzo3Yb7rx3pLSsPntqlJJKRmljlmG4ZLaqUdW+f7P08dkC7JrO2YrnH3lpDYXEpADm5ReQWFPOmZ31FgIM5BTz+jzV8tHwHNz25mNc/svz59a8B93tI5X43+0tuenIxh44UALD/cD7H8osD2BMRqTMXOBUTioiEJc0UijQAp8PBKf3b0qdza0b1aVNjvcT4aGZcPoQ1m7L44tu9RDkdREU5uP78fvz9k418snIX4wdm8NV3++rdpj9OG8E9cxpuyY0bHlvE768YygOeYK+ydVsOsW7LIb+youJSlq/fX6XuR8t3ctlpPZgx+0uSEmKYdcs4AAqLSnE6HX6ZYkXCnTGmJ/AqkAJkAVdaazdVqnMG8GegP/CUtfb2QLezzOXSO4UiImEqIEGhMeZR4EKgM9DfWruumjpRwCzgLMAFzLTWvhiI9ok0hGvO6XPcOn+cNoIop5OhJo2hJs1v3zmjO9M+LYmuGS3ITE3k261Z7M+ueSmJ42nlWY6jIdUUENbk+scW1bhvb1YugHemMCe3iN8+tYRWzeN47MZTvPV27DtK82axpKU1r/Y8O/cf44Mvt3H15N7ExUZV2b903V5aN4+nl8/yIyJNzGzgaWvt34wxlwPPAZMq1dkCXAtcBMQHuH1eiglFRMJToG7HvwOMB7bXUucXQHegBzAauNcY07nxmybS+GbdMo6nfjOO1i1q/l0uOTGW8QMzcDocJMRFM/O60Ywf6H6M9PIzenrr3XPV8CrBzwt3nFrlfE1lCY3qbN6Tw+9f+Mq7PW3mAn771BIAso8WsnXvEQ4fK2Rfdh73vryC257+gtfmf8+RvKIq57pnznKWr9/PDY8v4u1Fm6vsf/Hf63l47urG64xIPRhj0oEhwFxP0VxgiDH+d42stT9Ya9cANWd1amQuFzj0TqGISFgKyEyhtXYJgDGmtmpTgRestWXAAWPMO8DFwCON30KRxlXXAO2qyb35+Wk9iYl2snn3EQZ2T6FT2+acObwD732xzVvP6XBw48/68fS/3JPwk0d19DvPnZcP4T9f7WD1poOM7tuWPp1b8ZJPttFA27LnSK377391ZZWyeZ9uYt6nm/yWEKnsgy+388GX27n/2pFkVvM+p0gT1AHYba0tBbDWlhpj9njKDzT0l6Wk1D0bckxsFI6C4hpn7cNNJPQzEvoI6mc4iYQ+QnD62ZTeKeyI/0ziDtyD4kmpz4BXTn/hwku49POuaRXJbH41ZSC/mjKQnGOF7PjxKOnpLTgrvQWnjujEa/PXc/lZvfwyfI4Z3IGc/BJWbzrIRaf1pGfHVkwc0YnH565i1YaKd/7apydxy6WD+d9ZFctQDO/ThhXf1/8dx4YybeYC/vnQeWzZfZhObasm7QFYsu5H2rRuxgUTunvLvtuZQ0ZqIi0SY2mbUnPAWFxSRnSUI6jvToXL39naREIfm6KsrGOUlbmOX7EahYUlOBwODhyoOVNxuEhLax72/YyEPoL6GU4ioY9Q/346nY46xUNNKShsEPUZ8EB/4cJNJPSzf/dUvz7+7JTO5B4tIPdoATdN6c+hIwUcOHCUod1TmHn9aFolRHvrX3duH67bsJ/MtETuv6Yi6OzUtjnbPUtUXDiuS5MKCgF++8RCb/uq89Ey9/2l1+ZXzIY+9kb170OOHdCO04d1wOVy0bpFPNP/spiLJ3Zj8shODdvoExQJf2cboo91HfSaoJ1ApjEmyjNLGAVkeMqblDKXSw+PioiEqaaU4m8H4PtbWEea4KAoEkqG9EzjtGHuCXeHw0F6ywS//THRTm6a0p/bpw7yK7/zF0O4eUp/+nZpTUpyPOMHZgSszSeitoDwZC1Zu5d75izn3pdX8O6SrQAsXfdjlXqz313Hs+9UyZEFwIznvuSDL7cBsGnXYQ4fK6xS542PN3LD44v4btshFq3Zzf7DdUsidPBwPq98uIHSsrI6HS9Ni7V2P7AGuMxTdBmw2lrb4I+O1pvL/ai6iIiEn6YUFM4DfmWMcXpesL8A+H9BbpNI2BvSM43kJP9MpbExUQzumcZtUwcR5XRy0andqj323quHk9LC/9irJvdqtLY2tk+/3gXA7gO5zFv4g2exbvjaHmD5+v2s2LCfz7/Zw+Fjhcxftp38QnfOj/3Z+by9aAt7s3J58G+ruPWvX7AvO49j+cXc8exSnn/vOz79eheFRaU89uYaXv2P5f88iXaWr9/Hyg1Vl+2oyUsfrOfzb/awaWfOcevmFZRQXFJapbzM5cLuyD7h75RGdz1wszFmI3CzZxtjzHxjzDDP57HGmF3ArcB1xphdxpgzA9lIlzvTjIiIhKFALUkxC5gCtAU+McZkWWv7GmPmA3dba1cCrwMjgfK1me6z1m4NRPtEpHblawlO/4v7XcNT+rfl/FO6kNoygevP7+e3VEWzuGj+57w+PP/+9wD89JTOLPpmDznHqmYObco+XLaD2OgojuQVsXHHYW/5Kx9u8H7en53HVZN7e7d9M6re+dwy7+eDOQVVzl9SWsaeg7nMfvc7AL8EOu6g7TC9O7Vi36E8juYX0y2jBfsP51NU4p4hPJGH5G968nM6pidx77QRfuUfLd/BvM82c+vUgfTrknICZ5LGZK3dgHv8q1x+ts/nJUD7QLarMheaKRQRCVeByj46HZheTbnvgFcK3BCI9ojIyfPNoJreMoFUz6Oo3TKT/eq5gFF927Lmh4OM6deWAd1SGdg9lQde+5oyz8zbxRO7Me+zzYwb0I7Fa/cGrA8nq/xx0pp8/s1e9mbl1fn8ldehPJJbxPaD+9i4NYu5n25i+oUDmPX2WgDOH9ulSns2bM+mZ4eWOJ01/6K+Y/+xKmV7DrjXiMw+WvUxV5GauFxoplBEJEyFXaIZEWl8pw+vOTFwYrz7n5Xrz+/nLevSrgV3/HwwM99YxZh+bZk8spM3kUt0lJPPVu/2O0ezuGjyCiuWYztndCcumNiDX/35k4bsRoPYtOv4j3HWpDzgK/cbz1qN5bKOVMwwVg4In3/vO3JyixjVpw2XntaDFs1iAfdM5uY9OX6Jg95fuo3zxnT2bpfPMmrWR06Gy+UiKqopvXUiIiINRf+6i8gJe/bWCTz92/HEx1Z/P+nXF/Sjd6dW1e7r0T6Zqyb34hen9/Qrv/QnPUiIc5/vwgldOW9MZ2bdMo5Zt4zz1jljeIcqy0i8cMep3s8P3zC6Lt1pUtZtyapS9sbHG2usn5Prfhx32ff7uGfOcrb9eIT7X13J59/sYbdnJrDcvz53v+84beYC1m3J8r4rebyYcN+hPPZm5dZeSSKGy3X8vzMiIhKaFBSKyAmLi43yBnC+bps6iLuvGsawXuk1ru/ncDgYPzCjyvEx0U7+dO1ITunXljOGd+Rn47vidDpISoihTasE77GANwvq+WO7EOWs+OcrNTmBK87wDzZ9DeqeenIdDYKdB6o+5nmico4Vcd8rK9m694i3bNrMBX51yt93XPb9PgqL3e8lls8ULlm7l++2Hapy3jufX8bvX/iKsjIXJaX1y3Za5nJ5g1EJTS6XC4eeHxURCUt6fFRE6q1vl9b1Or5V8ziuObdPlfLbpg5i9Q8Hve8zTpnQFYDJIzt664zt3w6AiUPaM35QBr96eKF7e3AmPz+9B//5agenDe2A0wnzPtvMJ54Mo03NvM82B+R7fJfbWLBqN6P6tmWOZz3H8mQ3LpfLL7i//7WVbP/xqF8ynNrsO5SH0+kgzWcJlGsf+oxObZpzz9XDG6IbEgQuNFMoIhKuFBSKSJOV2jKB04dVvL/Yolms35IXL/5uot+8RZTTyYt3TOS/K3byk6HtiXI6OWd0Z+/+SyZ1p11qIuu2ZLF600G6Zybzw+4cHv31GJ6Y9433scvbpg7isbfWNHb3gu6H3TkUFlcsWbF+2yEeedPd70sndfeWl68L+d3WQ94bAC6Xi38v3caEQZm0SIz11ntrwSY2eLK1Vg4it+9ruPUlJfD0+KiISPhSUCgiIau6RClOp4OzfGYSfUVHOZk4OJNxA9pRXFJGdJST7GOFtG4Rz/3XjOSOZ5dyMKeA1pXWXgS4+uxeZB8p5L0vtnHasPb8d8VOAJ69bQJOByxfv58O6Um0T0ti249H+dNrKxu2s43khscWeT+XB4QAby74oUrdx95aw62XDGTBqt2M7NOGfy3eyr8Wb+W3lwykQ3oSf3xlhV/9aTMXcOGErt7HfsGdYTUtrRE6Io3OhavGx8NFRCS0KSgUkYgTHeUk2pNFMd3nEcdyUVFOrjmnN3ExUTzzzjounNCVcQPcgc1Px3YBoF+X1vx3xU5iop04HQ5O8TzGCtA1owVzZkyq8l5fOHj8H98AsOaHg96yJzxl1Xl70RbeXrTFu/2bp5bwwA1jaJcc33iNlEahtetFRMKXEs2IiFTjlP7tGNYrnXuvHs7kUZ2q7O/XNYVbpw6q87IOg3u4k9+cOjizXu0MRb9/dmmwmyB14HKBo5Y1MUVEJHRpplBExKNLuxYczCkgLibKW9axTfM6n+/WqQPZuvco73y+xbs24Ije6Vz6kx60TIrjSF4RSQkxFBWXsnTdj1x9di9enr/Be3xGaiJ7Drrfc4yNdlJUUr8MoCL14XK5tLaliEiY0kyhiIjHtHN68/srh5LsSZxSX/26pHDemM685JNw5frz+9Eyyf3OYotmsTgdDkrL3CFjtNNJquexyk5tmvOna0fy6wv6AfDEzWN57MZT/M5/37QRpLfyf/z1ijNNg7RdpDKtKCIiEr4UFIqIeMTFRNEtI7lRzj3rlnE8cfPYaveVL93Qsnkcd187CoDmie5lOIb1SmfOjEkkxEXTqnkcj9wwxtvW9ulJZKQk+p1rbP+2PPCrkdw2dZC3rHmzGL86nds2547LBjdMxyRiuNBMoYhIuNLjoyIiAVC+1mJ1fnpKZ3q2T6Z3p1akpiZx+Rk9Gd4rvdq6Kcnx/P7KobRu7p5RvOJM45f0xeFw0C4lkXYpidx79XBycovonpnMo2+u8S5uRrs+bgAAC4pJREFU73BAr06t6NS2uXe5iXLDTBpnjezkzZ564YSufoliJHJpSQoRkfCloFBEJMiio5z065oCuIO6SUPa11rfdzazVfM4Hv31GG5/xp28xXcmx/d9yDsvH8Jdzy/jYE4Bx/KLAbjnquFs//EoqzYe4P2l2wD3I7TxsdF+awxOHJzJTU8url8nJeQpKBQRCV96fFREJIw4a8gOGR3l5P5rRwL4LZ/RqW1zurd3B5njB7YjPrbqvcJm8RWznHdePqTa8/vOhPbvmsKlk7oz/cIB/N+VwwBon5bIpT/pwUWnduOfD513kr2SpkDrFIqIhC/NFIqIhLgyT6KalBZxtdaLi4nixTsmVgkc+3Vpzc9P6+EXLFb2l+ljceFOjnP/tSPZvDuH/l1TiI1xkhAXjdPh8K7L+JuLB3iDhx37Kh5PPWN4BwBionU/MiRpplBEJGwpKBQRCXHlC1XE+iylUZPqZhIdDgenDetQ63HNm1VkZM1MTSQzNbFKnX5dWrNu6yG/2aTyADA5qfaAVZq+MpcLh5avFxEJSwoKRURCXFpyPOeO6cTYWmb6AuGmKf3JyS3yK2uXksjVk3sxuGdakFolDeWskR3pnNkq2M0QEZFGoKBQRCTEORwOpozvFuxmEBsT5V1ew9e4gRlBaI00tHEDMkhLa86BA0ePX1lEREKKXuwQERERERGJYAoKRUREREREIpiCQhERERERkQimoFBERERERCSCKdGMiIhIEBljegKvAilAFnCltXZTpTpRwCzgLMAFzLTWvhjotoqISHjSTKGIiEhwzQaettb2BJ4Gnqumzi+A7kAPYDRwrzGmc8BaKCIiYU1BoYiISJAYY9KBIcBcT9FcYIgxpvLCjlOBF6y1ZdbaA8A7wMWBa6mIiIQzBYUiIiLB0wHYba0tBfD8d4+n3FdHYLvP9o5q6oiIiNSJ3ikUERGJECkpSfU+R1pa8wZoSdMXCf2MhD6C+hlOIqGPEJx+hlNQGAXgdDrqfaKGOEcoUD/DRyT0EdTPcFLfPvocH1XvxgTXTiDTGBNlrS31JJTJ8JT72gF0AlZ4tivPHB5PFEB2di5lZa46NzYlJYmsrGN1Pj5UREI/I6GPoH6Gk0joI9S/n06ng1atEuEkx0eHy1X3waGJGQssDnYjREQkoMYBS4LdiPowxiwEXrTW/s0YczlwjbV2YqU6VwGXAZNxZyldDYyz1m49wa/RGCkiEllOanwMp5nCFbg7vxcoDXJbRESkcUUB7aiYOQtl1wOvGmPuBrKBKwGMMfOBu621K4HXgZFA+VIV951EQAgaI0VEIkWdxsdwmikUERERERGRk6TsoyIiIiIiIhFMQaGIiIiIiEgEU1AoIiIiIiISwRQUioiIiIiIRDAFhSIiIiIiIhFMQaGIiIiIiEgEU1AoIiIiIiISwcJp8fp6M8b0BF4FUoAs4Epr7abaj2p6jDHbgALPH4DfWWs/MsaMAp4DEoBtwOXW2v2eY2rc11QYYx4FLgQ6A/2ttes85TVet7ruC6Za+rmNaq6rZ19IXVtjTAruxbi7AUW4F+S+zlp7oK59CcF+uoBvgTJP9Sustd96jjsPeAT3v9FfA1dba/OOty9YjDHvAF1w9+UYcLO1dk24/WxGsnC6JuE4Rmp8NNvQ+BhO/Qyb8RFCZ4zUTKG/2cDT1tqewNO4f4BC1UXW2kGePx8ZY5zA34AbPf37HJgJUNu+JuYdYDywvVJ5bdetrvuCqaZ+QqXrCrVfvyZ8bV3Aw9ZaY63tD2wGZta1L6HWT5/9Y3yuZ/mAlwS8AJxnre0OHAVuP96+IPultXagtXYw8Cgwx1Mebj+bkSzcrkm4jZEaHzU+hkU/ffaHy/gIITJGKij0MMakA0OAuZ6iucAQY0xa8FrVoIYCBdbaJZ7t2cAlJ7CvybDWLrHW7vQtq+261XVfY/fjeKrr53GE3LW11h6y1i70KVoGdKLufQm1ftZmMrDS567fbGDqCewLGmttjs9mMlAWjj+bkSpCrknI/fviS+NjjULuump8rFXIjY8QOmOkgsIKHYDd1tpSAM9/93jKQ9Ebxpi1xphnjDEtgY743Fmz1h4EnMaY1sfZ19TVdt3quq8pq3xdIcSvrecu5g3Ae9S9L6HWz3ILjTFrjDEPGmPiPGV+fQF2UPH3srZ9QWWMedEYswN4APglkfezGc7C8ZpEwhgZaT+DGh9Pfl+TEO7jI4TGGKmgMDyNs9YOBIYDDuCvQW6PNIxwva5P4X7GPlz6U5PK/exorR2G+1GoPsAfgtWwhmCtvdZa2xG4C/c7HSJNVbj+WxrJwvWaanwMg/ERQmOMVFBYYSeQaYyJAvD8N8NTHlLKH62w1hYCzwCn4L5j4p2WN8akAmXW2kPH2dfU1Xbd6rqvSarhukIIX1tP0oAewFRrbRl170uo9dP3eh4BXqSG64n77ufOE9jXJFhrXwcmAruIkJ/NCBBW1ySCxkiNjyF8XTU+ht/4CE17jFRQ6GHdWZjWAJd5ii4DVltrDwSvVSfPGJNojEn2fHYAl+Lu19dAgjFmrKfq9cA8z+fa9jVptV23uu4LXOtPXC3XFUL02hpj/oz7XYcLPAM51L0vIdVPY0wrY0yC53M0cBEV1/M/wHBjTA/P9vXAP05gX1AYY5KMMR18ts8DDgER8bMZCcLpmkTSGKnxEQjR66rxMTzGRwitMdLhcrnqe46wYYzphTvFaysgG3eKVxvcVp0cY0xX4G0gyvPne2C6tXavMWYM7gxF8VSkJN7nOa7GfU2FMWYWMAVoCxwEsqy1fWu7bnXdF0zV9RM4jxquq+eYkLq2xpi+wDpgI5DvKd5qrf1ZXfsSSv0EHsbdVhcQAywFfmOtPeY57nxPnShgNXCVtTb3ePuCwRjTBngXSARKcQ92t1trV4Xbz2YkC5drEq5jpMZHjY/h0k/CaHz0tClkxkgFhSIiIiIiIhFMj4+KiIiIiIhEMAWFIiIiIiIiEUxBoYiIiIiISARTUCgiIiIiIhLBFBSKiIiIiIhEMAWFIiIiIiIiESw62A0QkcAxxnTGvQ5QjLW2JMjNERERaRI0Pkqk00yhiIiIiIhIBFNQKCIiIiIiEsEcLpcr2G0QiWjGmAzgKWA8cAx4wlo7yxhzL9APKAXOBjYBV1trv/Ec1xt4FhgE7AbutNa+59mXAPwJuAhoCXwLnA60wf14zFXA/UAzz/c9EIi+ioiInCiNjyKBo5lCkSAyxjiB94FvgEzgJ8BvjDFneqqcD8wDWgN/B94xxsQYY2I8x/0XSAduBt4wxhjPcY8CQ4ExnmPvAMp8vnosYDzfd7dnABUREWkSND6KBJZmCkWCyBgzEphnre3oU3Yn0BPYDpxlrR3lKXfivuN5iafqPCDDWlvm2T8XsMB9QC4wqvyuqc+5O+O+E9rBWrvLU7YceNxa+2Zj9VNERORkaHwUCSxlHxUJrk5AhjHmsE9ZFLAY96C3s7zQWltmjNkFZHiKdpYPeB7bcd9NTQXigc21fO+PPp/zgKQ690BERKThaXwUCSAFhSLBtRPYaq3tUXmH552JDj7bTqA9sMdT1MEY4/QZ+DoCG4GDQAHQDfdjNyIiIqFG46NIACkoFAmu5cBRY8zvgFlAEdAbSPDsH2qMmQK8B0wHCoFlgAP3Hcw7jDGPAacA5wHDPXdM5wCPG2OuAPYBI4BVgeuWiIhIvWh8FAkgJZoRCSJrbSlwLu4MaVtx38V8EUj2VHkXmApkA1cAU6y1xdbaItyD3GTPMc8AV1prN3iOux13RrUVwCHgIfTzLiIiIULjo0hgKdGMSBPleTymu7X28mC3RUREpKnQ+CjS8HRnREREREREJIIpKBQREREREYlgenxUREREREQkgmmmUEREREREJIIpKBQREREREYlgCgpFREREREQimIJCERERERGRCKagUEREREREJIL9f9WRYSteJqAnAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 1080x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize = (15, 5))\n",
    "plt.subplot(1, 2, 1)\n",
    "EPOCH = np.arange(len(LOST))\n",
    "plt.plot(EPOCH, LOST)\n",
    "plt.xlabel('epoch')\n",
    "plt.ylabel('loss')\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(EPOCH, ACCURACY)\n",
    "plt.xlabel('epoch')\n",
    "plt.ylabel('accuracy')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_based_sequence(length_sentence):\n",
    "    index = np.random.randint(0, len(data) - sequence_length - 1)\n",
    "    x = np.array([data[index:index + sequence_length]])\n",
    "    initial_state, ids = sess.run([model.predict_state,model.predicting_ids], \n",
    "                                  feed_dict = {model.X: x})\n",
    "    ids = ids[0].tolist()\n",
    "\n",
    "    while len(ids) < length_sentence:\n",
    "        initial_state, ids_ = sess.run([model.predict_state,model.predicting_ids], \n",
    "                                      feed_dict = {model.X: [ids[-sequence_length:]],\n",
    "                                                  model.encoder_state: initial_state})\n",
    "        ids.extend(ids_[0].tolist())\n",
    "\n",
    "    return ''.join([rev_dictionary[i] for i in ids])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " te houge you not.\n",
      "\n",
      "DUKE OF YORK:\n",
      "See, good men, the means of mythe goue you not.\n",
      "\n",
      "DUKE OF YORK:\n",
      "Speak, good men, the most fair he goue you not.\n",
      "\n",
      "DUKE OF YORK:\n",
      "Speak, good mean, to my bread the goue you not.\n",
      "\n",
      "DUKE VINCENTIO:\n",
      "Speak, good mean, for the man b goue you knon\n",
      "To please. Go, give me of good, and the mouble\n",
      "Thgoue you know me.\n",
      "\n",
      "GLOUCESTER:\n",
      "I plove, I plant me the poor fathou undey thou go.\n",
      "\n",
      "GLOUCESTER:\n",
      "I plant, I plead me to her face ou undey though of\n",
      "peague, I plant. God plant me be the mouth, an undey though off\n",
      "peage, good and place of pale the people,\n",
      "Thatyned youth good people,\n",
      "Baganion pale bold, and the people may wned yout good peecedo,\n",
      "My power, and place and place the people,ed youg to pedge,\n",
      "people, power palace, and place and peace the d you got peed,\n",
      "people, poor place, and pale and place and here  you pot peed,\n",
      "people, poor place, and pale and partle peace,\n",
      "Thyou pot peep,\n",
      "poor, people, poor place, and appear and peace theou ppot peop,\n",
      "peror, poolight, poor peace, and appear and the pe\n"
     ]
    }
   ],
   "source": [
    "print(generate_based_sequence(1000))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
